using System;
using System.Collections.Generic;
using System.Text;
using RabbitsWare.Business.TwitterApollo.BusinessEntities;
using Yedda;
using System.Xml;
using System.Diagnostics;
using System.IO;
using System.Data;
using Microsoft.Practices.EnterpriseLibrary.Data;
using System.Data.Common;
using RabbitsWare.Business.TwitterApollo.BusinessLogic;

namespace RabbitsWare.Business.TwitterApollo.BusinessLogic
{
    public class ApolloManager
    {
        private static string m_userName = "TweetApollo";
        private static string m_pswWord = "negociosseguros";

        public static void Run()
        {
            Twitter twit = new Twitter();

            int lastProcessedMentionId = ApolloManager.GetLastProcessedMentionId(m_userName);
            XmlDocument xmlDoc = null;
            if (lastProcessedMentionId != -1)
            {
                xmlDoc = twit.GetMentionsAsXmlWithParams("TweetApollo", "negociosseguros", lastProcessedMentionId);
            }
            else 
            {
                xmlDoc = twit.GetMentionsAsXml("TweetApollo", "negociosseguros");
            }
            //XmlDocument xmlDoc = new XmlDocument();
            //StreamReader sr = new StreamReader(@"c:\Program Files\XML Marker\TwitterMentions.xml");
            //xmlDoc.LoadXml(sr.ReadToEnd());
            //sr.Close;
            if (xmlDoc != null)
            {
                XmlNodeList statuses = xmlDoc.SelectNodes("/statuses/status");
                if(statuses!=null && statuses.Count>0)
                {         
                    foreach (XmlNode status in statuses)
                    {
                        ProcessCommand(status.SelectSingleNode("./user/screen_name").InnerText, status.SelectSingleNode("./text").InnerText);

                        lastProcessedMentionId = int.Parse(statuses[0].SelectSingleNode("./id").InnerText);
                        ApolloManager.SetLastProcessedMentionId(m_userName, lastProcessedMentionId);
                    }
                }
            }
        }

        private static int GetLastProcessedMentionId(string tweetApolloUserName)
        {
            Database database = GetDatabase();
            DbCommand storedProcCommand = database.GetStoredProcCommand("[dbo].[TweetApolloGetLastProcessedMentionId]");
            database.AddInParameter(storedProcCommand, "@tweetApolloUserName", DbType.String, tweetApolloUserName);

            int lastProcessedMentionId = -1;
            using (IDataReader reader = database.ExecuteReader(storedProcCommand))
            {
                while (reader.Read())
                {
                    lastProcessedMentionId = reader.GetInt32(0);
                }
            }

            return lastProcessedMentionId;
        }

        private static void SetLastProcessedMentionId(string tweetApolloUserName, int lastProcessedMentionId)
        {
            Database database = GetDatabase();
            DbCommand storedProcCommand = database.GetStoredProcCommand("[dbo].[TweetApolloSetLastProcessedMentionId]");
            database.AddInParameter(storedProcCommand, "@tweetApolloUserName", DbType.String, tweetApolloUserName);
            database.AddInParameter(storedProcCommand, "@lastProcessedMentionId", DbType.Int32, lastProcessedMentionId);

            database.ExecuteReader(storedProcCommand);
        }

        static void ProcessCommand(string customerName, string command)
        {
            string[] tokens = command.Split(' ');
            if (!(tokens != null && tokens.Length > 0))
            {
                throw new ArgumentException("Command not found", "command");
            }

            switch (tokens[1])
            { 
                case "needhelp":
                    BeginHelpClient(customerName, tokens[2]);
                    break;
                case "endhelp":
                    EndHelpClient(customerName);
                    break;
            }
        }

        /// <summary>
        /// A customer with the name 'clientName' has requested help from 'companyName'
        /// </summary>
        /// <param name="clientName">The client's name</param>
        /// <param name="companyName">The company's name</param>
        /// <returns>The id of the company's operator that is going to help the client</returns>
        public static CompanyOperator BeginHelpClient(string customerName, string companyName)
        {
            if (String.IsNullOrEmpty(companyName))
            {
                throw new ArgumentException("A company name must be provided", "companyName");
            }

            Company company = CompanyManager.CreateCompany(companyName);
            if (company == null)
            {
                ApolloManager.SendMessageTo(customerName, String.Format("Company {0} not found.", companyName));
                return null;
            }

            if (company.Credits == 0)
            {
                ApolloManager.SendMessageTo(customerName, String.Format("Company {0} has not enough credits to perfom the operation.", companyName));
                return null;
            }

            CompanyOperator companyOperator = CompanyOperator.GetAvaiableCompanyOperator(company.Id);
            if (companyOperator == null)
            {
                ApolloManager.SendMessageTo(customerName, String.Format("Company {0} has no operators avaiable at the moment.", companyName));
                return null;
            }

            ApolloManager.SendPrivateMessageTo(customerName, String.Format("Operator {1} from company {2} is going to help you.", customerName, companyOperator.Name, companyName));
            ApolloManager.SendPrivateMessageTo(companyOperator.Name, String.Format("Customer @{0} has requested help.", customerName));

            return companyOperator;
        }

        public static void EndHelpClient(string companyOperatorName)
        {
            if (String.IsNullOrEmpty(companyOperatorName))
            {
                throw new ArgumentException("A company operator name must be provided", "companyOperatorName");
            }

            CompanyOperator companyOperator = CompanyOperator.CreateCompanyOperator(companyOperatorName);
            if (companyOperator != null)
            {
                EndHelpClient(companyOperator);
            }
        }

        public static void EndHelpClient(CompanyOperator companyOperator)
        {
            if (companyOperator == null)
            {
                throw new ArgumentException("A company operator must be provided", "companyOperator");
            }

            companyOperator.MarkAsAvaiable();
        }

        private static void SendMessageTo(string customerName, string message)
        {
            Twitter twitter = new Twitter();
            Console.WriteLine(String.Format("@{0} {1}", customerName, message));

            string res = twitter.Update("TweetApollo", "negociosseguros", String.Format("@{0} {1}", customerName, message), Twitter.OutputFormatType.XML);
        }

        private static void SendPrivateMessageTo(string customerName, string message)
        {
            Twitter twitter = new Twitter();
            Console.WriteLine(String.Format("d {0} {1}", customerName, message));
            string res = twitter.Update("TweetApollo", "negociosseguros", String.Format("d {0} {1}", customerName, message), Twitter.OutputFormatType.XML);
        }

        private static Database GetDatabase()
        {
            return DatabaseFactory.CreateDatabase("RabbitsWare");
        }
    }
}
